
import util from '../util.js'
import * as dat from 'dat.gui';
class CesiumVolumeClouds {
  /**
  * 构造函数 - 修改为接受现有viewer实例
  * @param {Object} viewer - 已存在的Cesium Viewer实例
  * @param {Object} options - 配置选项
  */
  constructor(viewer, options = {}) {
    // 检查Cesium是否已加载
    if (typeof Cesium === 'undefined') {
      throw new Error('Cesium is not loaded. Please include Cesium.js before this script.');
    }

    // 检查dat.GUI是否已加载
    if (typeof dat === 'undefined') {
      console.warn('dat.GUI is not loaded. No control panel will be available.');
    }

    if (!viewer || !(viewer instanceof Cesium.Viewer)) {
      throw new Error('Invalid Cesium Viewer instance provided');
    }
    this.viewer = viewer;
    // 设置默认配置
    this.defaults = {
      positions: [
        Cesium.Cartesian3.fromDegrees(-104.99819046398898, 39.7518794202664, 20000),
        Cesium.Cartesian3.fromDegrees(-105.2, 39.8, 20000),  // 第二个点位
        Cesium.Cartesian3.fromDegrees(-104.8, 39.6, 20000),  // 第三个点位
        Cesium.Cartesian3.fromDegrees(-105.0, 39.9, 20000)   // 第四个点位
      ],
      activePositionIndex: 0,  // 添加默认的原点索
      cloudConfig: {
        cloudCover: 0.5,        // 云覆盖度
        windSpeedRatio: 0.0002, // 风速
        fogColor: 3.0,
        length: 5000.0,
        width: 5000.0,
        height: 1000,
        cloudThickness: 1000,   // 云层厚度
        windVectorX: 100,
        windVectorY: 0,
        windVectorZ: 0,
      },
      terrainAssetId: 1,       // 默认地形资产ID
      flyToDuration: 1         // 飞行到目标位置的时间
    };

    this.gui = null;
    // 合并配置
    this.config = { ...this.defaults, ...options };
    this.cloudConfig = { ...this.defaults.cloudConfig, ...options.cloudConfig };

    // 创建体积云效果
    this.createVolumeClouds();

    // 创建控制面板（如果dat.GUI可用）
    if (typeof dat !== 'undefined') {
      this.createGuiControls();
    }

    // // 飞行到初始位置
    this.flyToActivePosition();
  }

  /**
   * 初始化Cesium Viewer
   * @param {string} containerId - 容器ID
   * @param {string} token - Cesium Ion令牌
   */
  initCesium(containerId, token) {
    Cesium.Ion.defaultAccessToken = token;

    // 创建Viewer实例
    this.viewer = new Cesium.Viewer(containerId, {
      // 可以在这里添加更多Viewer配置
    });

    // 设置地形
    this.viewer.scene.setTerrain(
      new Cesium.Terrain(
        Cesium.CesiumTerrainProvider.fromIonAssetId(this.config.terrainAssetId),
      )
    );
  }

  /**
   * 创建体积云效果
   */
  createVolumeClouds() {
    // 定义体积云的着色器
    const shader = this.getCloudShader();

    // 获取当前激活的位置
    const activePosition = this.config.positions[this.config.activePositionIndex];

    // 创建后处理阶段
    this.postProcessStage = this.viewer.scene.postProcessStages.add(
      new Cesium.PostProcessStage({
        fragmentShader: shader,
        uniforms: {
          fogColor: this.cloudConfig.fogColor,
          inverse: Cesium.Matrix4.inverse(
            Cesium.Transforms.eastNorthUpToFixedFrame(activePosition),
            new Cesium.Matrix4()
          ),
          positionX: this.cloudConfig.length,
          positionY: this.cloudConfig.width,
          positionZ: this.cloudConfig.height,
          cloudCover: this.cloudConfig.cloudCover,
          windSpeedRatio: this.cloudConfig.windSpeedRatio,
          cloudThickness: this.cloudConfig.cloudThickness,
          windVector: new Cesium.Cartesian3(
            this.cloudConfig.windVectorX,
            this.cloudConfig.windVectorY,
            this.cloudConfig.windVectorZ
          )
        }
      })
    );
  }

  /**
   * 获取云效果的着色器代码
   * @returns {string} 着色器代码
   */
  // getCloudShader() {
  //   return `
  //           uniform sampler2D colorTexture;// 颜色纹理
  //           uniform sampler2D depthTexture; // 深度纹理
  //           in vec2 v_textureCoordinates;  // 纹理坐标
  //           uniform mat4 inverse;// 逆矩阵
  //           uniform float cloudCover;// 云覆盖度
  //           uniform float windSpeedRatio;//风速
  //           uniform vec3 windVector;//方向
  //           uniform float positionX;// 位置X
  //           uniform float positionY;// 位置Y
  //           uniform float positionZ; // 位置Z
  //           uniform float cloudThickness; //云层厚度
  //           uniform float fogColor;

  //           // 计算射线与盒子的交点距离
  //           vec4 rayBoxDst(vec3 boundsMin, vec3 boundsMax,  vec3 rayOrigin, vec3 invRaydir) 
  //           {
  //               // 计算射线与盒子最小边界交点的距离
  //               vec3 t0 = (boundsMin - rayOrigin) * invRaydir;
  //               // 计算射线与盒子最大边界交点的距离
  //               vec3 t1 = (boundsMax - rayOrigin) * invRaydir;
  //               // 取t0和t1的最小值，得到射线进入盒子的点
  //               vec3 tmin = min(t0, t1);
  //               // 取t0和t1的最大值，得到射线出去盒子的点
  //               vec3 tmax = max(t0, t1);
  //               // 进入点的距离，取tmin的x、y、z中的最大值
  //               float dstA = max(max(tmin.x, tmin.y), tmin.z); 
  //               // 出去点的距离，取tmax的x、y、z中的最小值
  //               float dstB = min(tmax.x, min(tmax.y, tmax.z)); 
  //               // 射线到盒子的距离，取dstA和0中的最大值，确保距离非负
  //               float dstToBox = max(0., dstA);
  //               // 射线在盒子内部的距离，取(dstB - dstToBox)和0中的最大值，确保距离非负
  //               float dstInsideBox = max(0., dstB - dstToBox);
  //               // 返回一个vec4，包含射线到盒子的距离、射线在盒子内部的距离、进入点的距离和出去点的距离
  //               return vec4(dstToBox, dstInsideBox,dstA,dstB);
  //           } 

  //           // 定义圆周率常量
  //           const float PI = 3.14159265359;
  //           // 定义两倍圆周率常量
  //           const float TWO_PI = 6.28318530718;
  //           // 定义四倍圆周率常量
  //           const float FOUR_PI = 12.5663706144; 
  //           // 定义云的最大细节级别
  //           #define CLOUDS_MAX_LOD 2
  //           // 定义外部每次步进的距离
  //           #define CLOUDS_MARCH_STEP 100.0 
  //           // 定义云内每次步进的距离
  //           #define CLOUDS_DENS_MARCH_STEP 10.0
  //           // 定义最大步进次数
  //           #define MAXIMUM_CLOUDS_STEPS 300 
  //           // 定义最大视距 
  //           #define CLOUDS_MAX_VIEWING_DISTANCE 250000.0

  //           // 将值限制在0到1之间
  //           float saturate (float value) {
  //               // 使用clamp函数将值限制在0到1之间
  //               return clamp(value, 0.0, 1.0);
  //           }

  //           // 各向同性散射
  //           float isotropic() {
  //               // 返回1.0 / (4.0 * PI)的值，表示各向同性散射的系数
  //               return 1.0 / (4.0 * PI); 
  //           }

  //           // 瑞利散射
  //           float rayleigh(float costh) {
  //               // 根据瑞利散射公式计算散射系数
  //               return (3.0 / (16.0 * PI)) * (1.0 + pow(costh, 2.0));
  //           } 

  //           // 斯涅尔克散射
  //           float Schlick(float k, float costh) {
  //               // 根据斯涅尔克散射公式计算散射系数
  //               return (1.0 - k * k) / (FOUR_PI * pow(1.0 - k * costh, 2.0));
  //           }   

  //           // 定义一个相关参数，用于后续计算
  //           float g = 0.9; 

  //           // 哈希函数
  //           float hash(float p) {
  //               // 将输入值乘以一个常量并取小数部分
  //               p = fract(p * .1031);
  //               // 将结果乘以自身加上一个常量
  //               p *= p + 33.33;
  //               // 再次将结果乘以自身加上自身
  //               p *= p + p;
  //               // 返回最终结果的小数部分
  //               return fract(p);
  //           }

  //           // 噪声函数
  //           float noise(in vec3 x) {
  //               // 获取输入向量的整数部分
  //               vec3 p = floor(x);
  //               vec3 f = fract(x);// 获取输入向量的小数部分
  //               // 对小数部分进行平滑处理
  //               f = f*f*(3.0 - 2.0*f);
  //               // 计算一个基于整数部分的噪声值
  //               float n = p.x + p.y*157.0 + 113.0*p.z;
  //               // 使用混合函数和哈希函数生成最终的噪声值
  //               return mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
  //                       mix( hash(n+157.0), hash(n+158.0),f.x),f.y),
  //                       mix(mix( hash(n+113.0), hash(n+114.0),f.x),
  //                       mix(hash(n+270.0), hash(n+271.0),f.x),f.y),f.z);
  //           }

  //           // 计算云的密度
  //           float cloudDensity(vec3 p, vec3 wind, int lod, inout float heightRatio) {
  //               float finalCoverage = cloudCover; // 获取云覆盖度
  //               if (finalCoverage <= 0.1) {
  //                   return 0.0; // 如果云覆盖度太低，直接返回0
  //               }
  //               float height = p.z; // 获取高度
  //               heightRatio = height / (positionZ + cloudThickness); // 计算高度比率
  //               float positionResolution = 0.02; // 定义位置分辨率
  //               p = p * positionResolution + wind; // 调整位置并加上风向
  //               float shape = noise(p * 0.3); // 计算形状噪声
  //               float shapeHeight = noise(p * 0.05); // 计算高度形状噪声
  //               float bn = 0.50000 * noise(p); p = p * 2.0; // 计算基础噪声
  //               if (lod >= 1) {
  //                   bn += 0.20000 * noise(p); p = p * 2.11; // 如果细节级别较高，增加噪声
  //               }
  //               float cumuloNimbus = saturate((shapeHeight - 0.5) * 2.0); // 计算积雨云密度
  //               cumuloNimbus *= saturate(1.0 - pow(heightRatio - 0.5, 2.0) * 4.0); // 调整积雨云密度
  //               float cumulus = saturate(1.0 - pow(heightRatio - 0.25, 2.0) * 25.0) * shapeHeight; // 计算积云密度
  //               float stratoCumulus = saturate(1.0 - pow(heightRatio - 0.12, 2.0) * 60.0) * (1.0 - shapeHeight); // 计算层积云密度
  //               float dens = saturate(stratoCumulus + cumulus + cumuloNimbus) * 2.0 * finalCoverage; // 计算总密度
  //               dens -= 1.0 - shape; // 调整密度
  //               dens -= bn; // 减去基础噪声
  //               return clamp(dens, 0.0, 1.0); // 将密度限制在0到1之间
  //           }

  //           precision highp float; // 使用高精度浮点数
  //           uniform sampler2D noiseTexture; // 噪声纹理
  //           vec3 skyAmbientColor = vec3(0.705, 0.850, 0.952); // 天空环境光颜色
  //           vec3 groundAmbientColor = vec3(0.741, 0.898, 0.823); // 地面环境光颜色
  //           float distanceQualityR = 0.00005; // LOD/质量比率
  //           float minDistance = 10.0; // 避免在驾驶舱内出现云

  //           // 计算云的颜色和透明度
  //           vec4 calculate_clouds(
  //               vec3 start,
  //               vec3 dir,
  //               float maxDistance,
  //               vec3 light_dir,
  //               vec3 wind,
  //               vec2 bounds
  //           ) {
  //               vec4 cloud = vec4(0.0, 0.0, 0.0, 1.0); // 初始化云的颜色和透明度
  //               float startHeight = length(start); // 计算起始高度
  //               float absoluteMaxDistance = CLOUDS_MAX_VIEWING_DISTANCE; // 最大视距
  //               float tmin = bounds.x;
  //               float tmax = bounds.x + bounds.y; 
  //               tmin = max(tmin, minDistance);
  //               tmax = min(tmax, absoluteMaxDistance);
  //               float rayLength = tmax - tmin; // 步进总距离
  //               float longMarchStep = rayLength / float(MAXIMUM_CLOUDS_STEPS); // 外部步进距离
  //               longMarchStep = max(longMarchStep, CLOUDS_MARCH_STEP);
  //               float shortMarchStep = CLOUDS_DENS_MARCH_STEP; // 云内步进距离
  //               float numberApproachSteps = (CLOUDS_MARCH_STEP / CLOUDS_DENS_MARCH_STEP) * 2.0; 
  //               float distance = tmin; 
  //               float dens = 0.0;
  //               float marchStep;
  //               float lastDensity;  
  //               float kInScattering = 0.99; // 入射散射系数
  //               float dotLightRay = dot(dir, light_dir); // 计算光线与射线的点积
  //               float inScattering = Schlick(kInScattering, dotLightRay); // 计算入射散射
  //               float outScattering = isotropic(); // 计算各向同性散射
  //               float sunScatteringPhase = mix(outScattering, inScattering, dotLightRay); // 计算太阳散射相位
  //               float ambientScatteringPhase = isotropic(); // 计算环境散射相位
  //               bool inCloud = false; // 是否在云中
  //               float stepsBeforeExitingCloud = 0.0; // 离开云之前的步数

  //               for (int i = 0; i < MAXIMUM_CLOUDS_STEPS; i++) {
  //                   vec3 position = start + dir * distance; // 计算当前位置
  //                   int qualityRatio = int(distance * distanceQualityR);
  //                   int lod = CLOUDS_MAX_LOD - qualityRatio; // 计算细节级别
  //                   float heightRatio;

  //                   if (inCloud == true) {
  //                       marchStep = shortMarchStep; // 如果在云中，使用云内步进距离
  //                   } else {
  //                       marchStep = longMarchStep; // 如果不在云中，使用外部步进距离
  //                       lod = 0;
  //                   }

  //                   dens = cloudDensity(position, wind, lod, heightRatio); // 计算当前位置的云密度

  //                   if (dens > 0.01) {
  //                       if (inCloud != true) {
  //                           inCloud = true; // 如果进入云中，更新状态
  //                           stepsBeforeExitingCloud = numberApproachSteps;
  //                           distance = clamp(distance - CLOUDS_MARCH_STEP, tmin, tmax); // 回退一步
  //                           continue;
  //                       }

  //                       float deltaDens = clamp((dens - lastDensity) * 10.0, -1.0, 1.0); // 计算密度变化
  //                       float lighting = (abs(deltaDens - dotLightRay) / 2.0) * clamp((heightRatio - 0.02) * 20.0, 0.5, 1.0); // 计算光照
  //                       lastDensity = dens;
  //                       float scatteringCoeff = 0.15 * dens; // 计算散射系数
  //                       float extinctionCoeff = 0.01 * dens; // 计算消光系数

  //                       cloud.a *= exp(-extinctionCoeff * marchStep); // 更新透明度

  //                       float sunIntensityAtSurface = clamp(0.2 - dens, 0.0, 1.0); // 计算太阳强度
  //                       vec3 sunLight = lighting * czm_lightColor * sunIntensityAtSurface * czm_lightColor.z; // 计算太阳光
  //                       vec3 ambientSun = czm_lightColor * sunIntensityAtSurface * czm_lightColor.z * isotropic(); // 计算环境光
  //                       vec3 skyAmbientLight = (skyAmbientColor * czm_lightColor.z + ambientSun); // 计算天空环境光
  //                       vec3 groundAmbientLight = (groundAmbientColor * czm_lightColor.z * 0.5 + ambientSun); // 计算地面环境光
  //                       vec3 ambientLight = mix(groundAmbientLight, skyAmbientLight, heightRatio); // 混合环境光
  //                       vec3 stepScattering = scatteringCoeff * marchStep * (sunScatteringPhase * sunLight + ambientScatteringPhase * ambientLight); // 计算步进散射

  //                       cloud.rgb += cloud.a * stepScattering; // 更新云的颜色

  //                       if (cloud.a < 0.01) {
  //                           cloud.a = 0.0; // 如果透明度太低，设置为0
  //                           break;
  //                       }
  //                   } else {
  //                       if (stepsBeforeExitingCloud > 0.0) {
  //                           stepsBeforeExitingCloud--; // 减少离开云之前的步数
  //                       } else {
  //                           inCloud = false; // 如果不在云中，更新状态
  //                       }
  //                   }

  //                   distance += marchStep; // 更新距离

  //                   // 如果步进距离超出总距离，退出循环
  //                   if (distance > tmax) {
  //                       break; 
  //                   }
  //               } 

  //               cloud.a = (1.0 - cloud.a); // 更新透明度
  //               return cloud; // 返回云的颜色和透明度
  //           }

  //           void main() {
  //               out_FragColor = texture(colorTexture, v_textureCoordinates); // 获取颜色纹理
  //               vec4 rawDepthColor = texture(depthTexture, v_textureCoordinates); // 获取深度纹理
  //               float depth = czm_unpackDepth(rawDepthColor); // 解压深度值

  //               vec4 eyeCoordinate4 = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth); // 将窗口坐标转换为眼睛坐标
  //               vec3 eyeCoordinate3 = eyeCoordinate4.xyz / eyeCoordinate4.w; 
  //               vec4 worldCoordinate4 = czm_inverseView * vec4(eyeCoordinate3, 1.); // 将眼睛坐标转换为世界坐标
  //               vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;
  //               vec4 worldPos = inverse * vec4(worldCoordinate, 1.); // 计算世界位置
  //               vec4 cameraPos = inverse * vec4(czm_viewerPositionWC, 1.); // 计算相机位置
  //               vec3 vDirection = worldPos.xyz - cameraPos.xyz; // 计算方向
  //               vec3 rayDir = normalize(vDirection); // 归一化方向
  //               vec3 dim = vec3(positionX, positionY, positionZ); // 盒子的长宽高
  //               vec3 box_min = vec3(0.) - dim / 2.; // 盒子的最小边界
  //               vec3 box_max = vec3(0.) + dim / 2.; // 盒子的最大边界
  //               vec4 bounds = rayBoxDst(box_min, box_max, cameraPos.xyz, 1.0 / rayDir); // 计算射线与盒子的交点
  //               bounds.x = max(bounds.x, 0.0);

  //               if (bounds.z > bounds.w) return; // 如果射线在盒子外，直接返回

  //               vec3 p = cameraPos.xyz + bounds.x * rayDir; // 计算射线起点
  //               p.z += 50.; // 调整射线起点的高度
  //               vec3 posToEye = worldPos.xyz - cameraPos.xyz; // 计算从相机到位置的向量
  //               vec3 direction = normalize(posToEye); // 归一化方向
  //               vec3 lightDirection = normalize(czm_sunPositionWC); // 获取光线方向
  //               float distance = length(posToEye); // 计算距离

  //               if (depth == 1.0) {
  //                   distance = CLOUDS_MAX_VIEWING_DISTANCE; // 如果深度为1.0，设置最大视距
  //               }

  //               vec3 wind = windVector * czm_frameNumber * windSpeedRatio; // 计算风向
  //               vec4 clouds = calculate_clouds(
  //                   cameraPos.xyz, // 相机位置
  //                   direction, // 方向
  //                   distance, // 最大距离
  //                   lightDirection, // 光线方向
  //                   wind, // 风向
  //                   bounds.xy // 交点范围
  //               );

  //               clouds.rgb *= fogColor; // 调整云的颜色强度
  //               vec4 color = out_FragColor; // 获取当前颜色
  //               color = mix(color, clouds, clouds.a ); // 混合颜色
  //               float exposure = 1.2; // 设置曝光度
  //               color = vec4(1.0 - exp(-exposure * color)); // 应用曝光调整
  //               out_FragColor = color; // 输出最终颜色
  //           }
  //       `;
  // }


  getCloudShader() {
    return `
            uniform sampler2D colorTexture;// 颜色纹理
            uniform sampler2D depthTexture; // 深度纹理
            in vec2 v_textureCoordinates;  // 纹理坐标
            uniform mat4 inverse;// 逆矩阵
            uniform float cloudCover;// 云覆盖度
            uniform float windSpeedRatio;//风速
            uniform vec3 windVector;//方向
            uniform float positionX;// 位置X
            uniform float positionY;// 位置Y
            uniform float positionZ; // 位置Z
            uniform float cloudThickness; //云层厚度
            uniform float fogColor;
            
            // 计算射线与盒子的交点距离
            vec4 rayBoxDst(vec3 boundsMin, vec3 boundsMax,  vec3 rayOrigin, vec3 invRaydir) 
            {
                // 计算射线与盒子最小边界交点的距离
                vec3 t0 = (boundsMin - rayOrigin) * invRaydir;
                // 计算射线与盒子最大边界交点的距离
                vec3 t1 = (boundsMax - rayOrigin) * invRaydir;
                // 取t0和t1的最小值，得到射线进入盒子的点
                vec3 tmin = min(t0, t1);
                // 取t0和t1的最大值，得到射线出去盒子的点
                vec3 tmax = max(t0, t1);
                // 进入点的距离，取tmin的x、y、z中的最大值
                float dstA = max(max(tmin.x, tmin.y), tmin.z); 
                // 出去点的距离，取tmax的x、y、z中的最小值
                float dstB = min(tmax.x, min(tmax.y, tmax.z)); 
                // 射线到盒子的距离，取dstA和0中的最大值，确保距离非负
                float dstToBox = max(0., dstA);
                // 射线在盒子内部的距离，取(dstB - dstToBox)和0中的最大值，确保距离非负
                float dstInsideBox = max(0., dstB - dstToBox);
                // 返回一个vec4，包含射线到盒子的距离、射线在盒子内部的距离、进入点的距离和出去点的距离
                return vec4(dstToBox, dstInsideBox,dstA,dstB);
            } 
            
            // 定义圆周率常量
            const float PI = 3.14159265359;
            // 定义两倍圆周率常量
            const float TWO_PI = 6.28318530718;
            // 定义四倍圆周率常量
            const float FOUR_PI = 12.5663706144; 
            // 定义云的最大细节级别
            #define CLOUDS_MAX_LOD 2
            // 定义外部每次步进的距离
            #define CLOUDS_MARCH_STEP 100.0 
            // 定义云内每次步进的距离
            #define CLOUDS_DENS_MARCH_STEP 10.0
            // 定义最大步进次数
            #define MAXIMUM_CLOUDS_STEPS 300 
            // 定义最大视距 
            #define CLOUDS_MAX_VIEWING_DISTANCE 250000.0
            
            // 将值限制在0到1之间
            float saturate (float value) {
                // 使用clamp函数将值限制在0到1之间
                return clamp(value, 0.0, 1.0);
            }
            
            // 各向同性散射
            float isotropic() {
                // 返回1.0 / (4.0 * PI)的值，表示各向同性散射的系数
                return 1.0 / (4.0 * PI); 
            }
            
            // 瑞利散射
            float rayleigh(float costh) {
                // 根据瑞利散射公式计算散射系数
                return (3.0 / (16.0 * PI)) * (1.0 + pow(costh, 2.0));
            } 
            
            // 斯涅尔克散射
            float Schlick(float k, float costh) {
                // 根据斯涅尔克散射公式计算散射系数
                return (1.0 - k * k) / (FOUR_PI * pow(1.0 - k * costh, 2.0));
            }   
            
            // 定义一个相关参数，用于后续计算
            float g = 0.9; 
            
            // 哈希函数
            float hash(float p) {
                // 将输入值乘以一个常量并取小数部分
                p = fract(p * .1031);
                // 将结果乘以自身加上一个常量
                p *= p + 33.33;
                // 再次将结果乘以自身加上自身
                p *= p + p;
                // 返回最终结果的小数部分
                return fract(p);
            }
            
            // 噪声函数
            float noise(in vec3 x) {
                // 获取输入向量的整数部分
                vec3 p = floor(x);
                vec3 f = fract(x);// 获取输入向量的小数部分
                // 对小数部分进行平滑处理
                f = f*f*(3.0 - 2.0*f);
                // 计算一个基于整数部分的噪声值
                float n = p.x + p.y*157.0 + 113.0*p.z;
                // 使用混合函数和哈希函数生成最终的噪声值
                return mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
                        mix( hash(n+157.0), hash(n+158.0),f.x),f.y),
                        mix(mix( hash(n+113.0), hash(n+114.0),f.x),
                        mix(hash(n+270.0), hash(n+271.0),f.x),f.y),f.z);
            }
            
            // 计算云的密度
            float cloudDensity(vec3 p, vec3 wind, int lod, inout float heightRatio) {
                float finalCoverage = cloudCover; // 获取云覆盖度
                if (finalCoverage <= 0.1) {
                    return 0.0; // 如果云覆盖度太低，直接返回0
                }
                float height = p.z; // 获取高度
                heightRatio = height / (positionZ + cloudThickness); // 计算高度比率
                float positionResolution = 0.02; // 定义位置分辨率
                p = p * positionResolution + wind; // 调整位置并加上风向
                float shape = noise(p * 0.3); // 计算形状噪声
                float shapeHeight = noise(p * 0.05); // 计算高度形状噪声
                float bn = 0.50000 * noise(p); p = p * 2.0; // 计算基础噪声
                if (lod >= 1) {
                    bn += 0.20000 * noise(p); p = p * 2.11; // 如果细节级别较高，增加噪声
                }
                float cumuloNimbus = saturate((shapeHeight - 0.5) * 2.0); // 计算积雨云密度
                cumuloNimbus *= saturate(1.0 - pow(heightRatio - 0.5, 2.0) * 4.0); // 调整积雨云密度
                float cumulus = saturate(1.0 - pow(heightRatio - 0.25, 2.0) * 25.0) * shapeHeight; // 计算积云密度
                float stratoCumulus = saturate(1.0 - pow(heightRatio - 0.12, 2.0) * 60.0) * (1.0 - shapeHeight); // 计算层积云密度
                float dens = saturate(stratoCumulus + cumulus + cumuloNimbus) * 2.0 * finalCoverage; // 计算总密度
                dens -= 1.0 - shape; // 调整密度
                dens -= bn; // 减去基础噪声
                return clamp(dens, 0.0, 1.0); // 将密度限制在0到1之间
            }
            
            precision highp float; // 使用高精度浮点数
            uniform sampler2D noiseTexture; // 噪声纹理
            vec3 skyAmbientColor = vec3(0.705, 0.850, 0.952); // 天空环境光颜色
            vec3 groundAmbientColor = vec3(0.741, 0.898, 0.823); // 地面环境光颜色
            float distanceQualityR = 0.00005; // LOD/质量比率
            float minDistance = 10.0; // 避免在驾驶舱内出现云
            
            // 计算云的颜色和透明度
            vec4 calculate_clouds(
                vec3 start,
                vec3 dir,
                float maxDistance,
                vec3 light_dir,
                vec3 wind,
                vec2 bounds
            ) {
                vec4 cloud = vec4(0.0, 0.0, 0.0, 1.0); // 初始化云的颜色和透明度
                float startHeight = length(start); // 计算起始高度
                float absoluteMaxDistance = CLOUDS_MAX_VIEWING_DISTANCE; // 最大视距
                float tmin = bounds.x;
                float tmax = bounds.x + bounds.y; 
                tmin = max(tmin, minDistance);
                tmax = min(tmax, absoluteMaxDistance);
                float rayLength = tmax - tmin; // 步进总距离
                float longMarchStep = rayLength / float(MAXIMUM_CLOUDS_STEPS); // 外部步进距离
                longMarchStep = max(longMarchStep, CLOUDS_MARCH_STEP);
                float shortMarchStep = CLOUDS_DENS_MARCH_STEP; // 云内步进距离
                float numberApproachSteps = (CLOUDS_MARCH_STEP / CLOUDS_DENS_MARCH_STEP) * 2.0; 
                float distance = tmin; 
                float dens = 0.0;
                float marchStep;
                float lastDensity;  
                float kInScattering = 0.99; // 入射散射系数
                float dotLightRay = dot(dir, light_dir); // 计算光线与射线的点积
                float inScattering = Schlick(kInScattering, dotLightRay); // 计算入射散射
                float outScattering = isotropic(); // 计算各向同性散射
                float sunScatteringPhase = mix(outScattering, inScattering, dotLightRay); // 计算太阳散射相位
                float ambientScatteringPhase = isotropic(); // 计算环境散射相位
                bool inCloud = false; // 是否在云中
                float stepsBeforeExitingCloud = 0.0; // 离开云之前的步数
                
                for (int i = 0; i < MAXIMUM_CLOUDS_STEPS; i++) {
                    vec3 position = start + dir * distance; // 计算当前位置
                    int qualityRatio = int(distance * distanceQualityR);
                    int lod = CLOUDS_MAX_LOD - qualityRatio; // 计算细节级别
                    float heightRatio;
                    
                    if (inCloud == true) {
                        marchStep = shortMarchStep; // 如果在云中，使用云内步进距离
                    } else {
                        marchStep = longMarchStep; // 如果不在云中，使用外部步进距离
                        lod = 0;
                    }
                    
                    dens = cloudDensity(position, wind, lod, heightRatio); // 计算当前位置的云密度
                    
                    if (dens > 0.01) {
                        if (inCloud != true) {
                            inCloud = true; // 如果进入云中，更新状态
                            stepsBeforeExitingCloud = numberApproachSteps;
                            distance = clamp(distance - CLOUDS_MARCH_STEP, tmin, tmax); // 回退一步
                            continue;
                        }
                        
                        float deltaDens = clamp((dens - lastDensity) * 10.0, -1.0, 1.0); // 计算密度变化
                        float lighting = (abs(deltaDens - dotLightRay) / 2.0) * clamp((heightRatio - 0.02) * 20.0, 0.5, 1.0); // 计算光照
                        lastDensity = dens;
                        float scatteringCoeff = 0.15 * dens; // 计算散射系数
                        float extinctionCoeff = 0.01 * dens; // 计算消光系数
                        
                        cloud.a *= exp(-extinctionCoeff * marchStep); // 更新透明度
                        
                        float sunIntensityAtSurface = clamp(0.2 - dens, 0.0, 1.0); // 计算太阳强度
                        vec3 sunLight = lighting * czm_lightColor * sunIntensityAtSurface * czm_lightColor.z; // 计算太阳光
                        vec3 ambientSun = czm_lightColor * sunIntensityAtSurface * czm_lightColor.z * isotropic(); // 计算环境光
                        vec3 skyAmbientLight = (skyAmbientColor * czm_lightColor.z + ambientSun); // 计算天空环境光
                        vec3 groundAmbientLight = (groundAmbientColor * czm_lightColor.z * 0.5 + ambientSun); // 计算地面环境光
                        vec3 ambientLight = mix(groundAmbientLight, skyAmbientLight, heightRatio); // 混合环境光
                        vec3 stepScattering = scatteringCoeff * marchStep * (sunScatteringPhase * sunLight + ambientScatteringPhase * ambientLight); // 计算步进散射
                        
                        cloud.rgb += cloud.a * stepScattering; // 更新云的颜色
                        
                        if (cloud.a < 0.01) {
                            cloud.a = 0.0; // 如果透明度太低，设置为0
                            break;
                        }
                    } else {
                        if (stepsBeforeExitingCloud > 0.0) {
                            stepsBeforeExitingCloud--; // 减少离开云之前的步数
                        } else {
                            inCloud = false; // 如果不在云中，更新状态
                        }
                    }
                    
                    distance += marchStep; // 更新距离
                    
                    // 如果步进距离超出总距离，退出循环
                    if (distance > tmax) {
                        break; 
                    }
                } 
                
                cloud.a = (1.0 - cloud.a); // 更新透明度
                return cloud; // 返回云的颜色和透明度
            }
            
            void main() {
                out_FragColor = texture(colorTexture, v_textureCoordinates); // 获取颜色纹理
                vec4 rawDepthColor = texture(depthTexture, v_textureCoordinates); // 获取深度纹理
                float depth = czm_unpackDepth(rawDepthColor); // 解压深度值
                
                vec4 eyeCoordinate4 = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth); // 将窗口坐标转换为眼睛坐标
                vec3 eyeCoordinate3 = eyeCoordinate4.xyz / eyeCoordinate4.w; 
                vec4 worldCoordinate4 = czm_inverseView * vec4(eyeCoordinate3, 1.); // 将眼睛坐标转换为世界坐标
                vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;
                vec4 worldPos = inverse * vec4(worldCoordinate, 1.); // 计算世界位置
                vec4 cameraPos = inverse * vec4(czm_viewerPositionWC, 1.); // 计算相机位置
                vec3 vDirection = worldPos.xyz - cameraPos.xyz; // 计算方向
                vec3 rayDir = normalize(vDirection); // 归一化方向
                vec3 dim = vec3(positionX, positionY, positionZ); // 盒子的长宽高
                vec3 box_min = vec3(0.) - dim / 2.; // 盒子的最小边界
                vec3 box_max = vec3(0.) + dim / 2.; // 盒子的最大边界
                vec4 bounds = rayBoxDst(box_min, box_max, cameraPos.xyz, 1.0 / rayDir); // 计算射线与盒子的交点
                bounds.x = max(bounds.x, 0.0);
                
                if (bounds.z > bounds.w) return; // 如果射线在盒子外，直接返回
                
                vec3 p = cameraPos.xyz + bounds.x * rayDir; // 计算射线起点
                p.z += 50.; // 调整射线起点的高度
                vec3 posToEye = worldPos.xyz - cameraPos.xyz; // 计算从相机到位置的向量
                vec3 direction = normalize(posToEye); // 归一化方向
                vec3 lightDirection = normalize(czm_sunPositionWC); // 获取光线方向
                float distance = length(posToEye); // 计算距离
                
                if (depth == 1.0) {
                    distance = CLOUDS_MAX_VIEWING_DISTANCE; // 如果深度为1.0，设置最大视距
                }
                
                vec3 wind = windVector * czm_frameNumber * windSpeedRatio; // 计算风向
                vec4 cloud = calculate_clouds(cameraPos.xyz, direction, distance, lightDirection, wind, bounds.xy); // 计算云的颜色和透明度
                out_FragColor.rgb = mix(out_FragColor.rgb, cloud.rgb, cloud.a); // 混合云的颜色和原始颜色
            }
        `;
  }

  /**
   * 创建GUI控制面板
   */
  // createGuiControls() {
  //   this.gui = new dat.GUI();
  //   this.gui.domElement.style = 'position:absolute;right:355px'

  //   // 云覆盖度控制面板
  //   const cloudCoverFolder = this.gui.addFolder('云覆盖度');
  //   cloudCoverFolder.add(this.cloudConfig, 'cloudCover', 0, 1, 0.01)
  //     .onChange(value => this.postProcessStage.uniforms.cloudCover = value);
  //   cloudCoverFolder.add(this.cloudConfig, 'fogColor', 1, 6, 0.01)
  //     .onChange(value => this.postProcessStage.uniforms.fogColor = value);
  //   cloudCoverFolder.open();

  //   // 风速控制面板
  //   const windSpeedFolder = this.gui.addFolder('风速');
  //   windSpeedFolder.add(this.cloudConfig, 'windSpeedRatio', 0, 0.001, 0.0002)
  //     .onChange(value => this.postProcessStage.uniforms.windSpeedRatio = value);
  //   windSpeedFolder.open();

  //   // 云范围控制面板
  //   const dimensionFolder = this.gui.addFolder('长宽高');
  //   dimensionFolder.add(this.cloudConfig, 'length', 0, 10000, 0.1)
  //     .onChange(value => this.postProcessStage.uniforms.positionX = value);
  //   dimensionFolder.add(this.cloudConfig, 'width', 0, 10000, 0.1)
  //     .onChange(value => this.postProcessStage.uniforms.positionY = value);
  //   dimensionFolder.add(this.cloudConfig, 'height', 0, 10000, 0.1)
  //     .onChange(value => this.postProcessStage.uniforms.positionZ = value);
  //   dimensionFolder.open();

  //   // 云层厚度控制面板
  //   const thicknessFolder = this.gui.addFolder('云层厚度');
  //   thicknessFolder.add(this.cloudConfig, 'cloudThickness', 0, 10000, 0.1)
  //     .onChange(value => this.postProcessStage.uniforms.cloudThickness = value);
  //   thicknessFolder.open();

  //   // 风向控制面板
  //   const windDirFolder = this.gui.addFolder('云层流动方向');
  //   windDirFolder.add(this.cloudConfig, 'windVectorX', -180, 180, 0.1)
  //     .onChange(() => this.updateWindVector());
  //   windDirFolder.add(this.cloudConfig, 'windVectorY', -180, 180, 0.1)
  //     .onChange(() => this.updateWindVector());
  //   windDirFolder.add(this.cloudConfig, 'windVectorZ', 0, 100, 0.1)
  //     .onChange(() => this.updateWindVector());
  //   windDirFolder.open();
  // }


  /**
    * 创建GUI控制面板
    */
  createGuiControls() {
    this.gui = new dat.GUI();
    this.gui.domElement.style = 'position:absolute;right:355px'
    // 添加点位切换控制
    const positionFolder = this.gui.addFolder('点位控制');
    positionFolder.add(this, 'nextPosition').name('下一个点位');
    positionFolder.add(this, 'prevPosition').name('上一个点位');
    positionFolder.open();

    // 云配置控制面板
    const cloudFolder = this.gui.addFolder('云配置');
    cloudFolder.add(this.cloudConfig, 'cloudCover', 0, 1).name('云覆盖度').onChange(value => {
      this.postProcessStage.uniforms.cloudCover = value;
    });
    cloudFolder.add(this.cloudConfig, 'windSpeedRatio', 0, 0.001).name('风速比例').onChange(value => {
      this.postProcessStage.uniforms.windSpeedRatio = value;
    });
    cloudFolder.add(this.cloudConfig, 'fogColor', 0, 5).name('雾色强度').onChange(value => {
      this.postProcessStage.uniforms.fogColor = value;
    });
    cloudFolder.add(this.cloudConfig, 'length', 1000, 10000).name('云长度').onChange(value => {
      this.postProcessStage.uniforms.positionX = value;
    });
    cloudFolder.add(this.cloudConfig, 'width', 1000, 10000).name('云宽度').onChange(value => {
      this.postProcessStage.uniforms.positionY = value;
    });
    cloudFolder.add(this.cloudConfig, 'height', 500, 2000).name('云高度').onChange(value => {
      this.postProcessStage.uniforms.positionZ = value;
    });
    cloudFolder.add(this.cloudConfig, 'cloudThickness', 500, 2000).name('云层厚度').onChange(value => {
      this.postProcessStage.uniforms.cloudThickness = value;
    });
    cloudFolder.add(this.cloudConfig, 'windVectorX', -200, 200).name('风向X').onChange(value => {
      this.postProcessStage.uniforms.windVector.x = value;
    });
    cloudFolder.add(this.cloudConfig, 'windVectorY', -200, 200).name('风向Y').onChange(value => {
      this.postProcessStage.uniforms.windVector.y = value;
    });
    cloudFolder.add(this.cloudConfig, 'windVectorZ', -200, 200).name('风向Z').onChange(value => {
      this.postProcessStage.uniforms.windVector.z = value;
    });
    cloudFolder.open();
  }

  /**
   * 更新风向向量
   */
  updateWindVector() {
    this.postProcessStage.uniforms.windVector = new Cesium.Cartesian3(
      this.cloudConfig.windVectorX,
      this.cloudConfig.windVectorY,
      this.cloudConfig.windVectorZ
    );
  }

  /**
   * 飞行到初始位置
   */
  flyToInitialPosition() {
    this.viewer.camera.flyTo({
      destination: this.config.position,
      orientation: {
        heading: Cesium.Math.toRadians(0.0),
        pitch: Cesium.Math.toRadians(-90),
        roll: 0.0,
      },
      duration: this.config.flyToDuration,
    });
  }


  /**
      * 飞行到当前激活的点位
      */
  flyToActivePosition() {
    const activePosition = this.config.positions[this.config.activePositionIndex];
    this.viewer.camera.flyTo({
      destination: activePosition,
      orientation: {
        heading: Cesium.Math.toRadians(0.0),
        pitch: Cesium.Math.toRadians(-90),
        roll: 0.0,
      },
      duration: this.config.flyToDuration,
    });
    // 更新云效果位置
    this.updateCloudPosition(activePosition);
  }



  /**
   * 更新云效果的位置
   * @param {Cesium.Cartesian3} position - 新的位置
   */
  updateCloudPosition(position) {
    if (this.postProcessStage) {
      this.postProcessStage.uniforms.inverse = Cesium.Matrix4.inverse(
        Cesium.Transforms.eastNorthUpToFixedFrame(position),
        new Cesium.Matrix4()
      );
    }
  }

  /**
   * 切换到下一个点位
   */
  nextPosition() {
    this.config.activePositionIndex = (this.config.activePositionIndex + 1) % this.config.positions.length;
    this.flyToActivePosition();
  }

  /**
   * 切换到上一个点位
   */
  prevPosition() {
    this.config.activePositionIndex = (this.config.activePositionIndex - 1 + this.config.positions.length) % this.config.positions.length;
    this.flyToActivePosition();
  }



  /**
   * 销毁实例，释放资源
   */
  destroy() {
    // 移除后处理阶段
    if (this.postProcessStage) {
      this.viewer.scene.postProcessStages.remove(this.postProcessStage);
      this.postProcessStage = null;
    }

    // 销毁GUI控制面板
    if (this.gui) {
      this.gui.destroy();
      this.gui = null;
    }
  }

  /**
   * 获取Cesium Viewer实例
   * @returns {Cesium.Viewer} Cesium Viewer实例
   */
  getViewer() {
    return this.viewer;
  }

  /**
   * 更新云的位置
   * @param {Cesium.Cartesian3} position - 新的位置
   */
  updatePosition(position) {
    this.config.position = position;
    this.postProcessStage.uniforms.inverse = Cesium.Matrix4.inverse(
      Cesium.Transforms.eastNorthUpToFixedFrame(this.config.position),
      new Cesium.Matrix4()
    );
  }
}
// 如果是在浏览器环境且支持模块，导出模块
if (typeof window !== 'undefined' && typeof window.exports === 'undefined') {
  window.CesiumVolumeClouds = CesiumVolumeClouds;
}

// 如果是在模块化环境中
if (typeof module !== 'undefined' && module.exports) {
  module.exports = CesiumVolumeClouds;
}

export default CesiumVolumeClouds;

